using OpenAI.ObjectModels.RequestModels;
using Microsoft.AspNetCore.SignalR.Client;
using MultiAgentsShared;
using MultiAgentsClient.ChatDataStructures;
using static MultiAgentsClient.Manager.MessageWebviewOperator;
using static MultiAgentsClient.Manager.MessageManager;
using static MultiAgentsClient.Manager.ProjectManager;

namespace MultiAgentsClient.Service.SignalRService;

public class SignalRChatService : SignalRClientServiceBase
{
    public enum ApiRequestType
    {
        SendToolResultApiRequest,
        SendUserMsgApiRequest,
        ResendMessageApiRequest,
        OverrideMessageApiRequest,
        SendUserMessageWithoutLLMResponseApiRequest,
        SendNodeMessageApiRequest,
        StopUserMsgApiRequest,

        CreateProjectApiRequest,
        DeleteProjectApiRequest,
        CreateChatRoomApiRequest,
        SwitchChatRoomApiRequest,
        GetFileContentApiRequest,
        SwitchChatRoomBranchApiRequest,
    }

    public SignalRChatService() : base("chatHub") { }

    protected override void HubMethodRegistration()
    {
        hubConnection.On<int, string, string?>("SendUserMsgApiResponse", SendUserMsgApiResponse);
        hubConnection.On<int, string>("OverrideMessageApiResponse", OverrideMessageApiResponse);
        hubConnection.On<int, int, int, string, string, List<int>?, DateTime >("SendToolResultApiResponse", SendToolResultApiResponse);
        hubConnection.On<Dictionary<string, object?>> ("ReceiveStream", ReceiveStream);
        hubConnection.On<int, List<string>>("ReplyAssistantOptionsResponse", ReplyAssistantOptionsResponse);
        hubConnection.On<int, string, string>("CreateProjectApiResponse", CreateProjectApiResponse);
        hubConnection.On<int>("DeleteProjectApiResponse", DeleteProjectApiResponse);
        hubConnection.On<int, int, string>("CreateChatRoomApiResponse", CreateChatRoomApiResponse);
        hubConnection.On<int, int, List<string>, int>("SwitchChatRoomApiResponse", SwitchChatRoomApiResponse);
        hubConnection.On<int, int>("SwitchChatRoomBranchApiResponse", SwitchChatRoomBranchApiResponse);
        hubConnection.On<int, string, string>("GetFileContentApiResponse", GetFileContentApiResponse);
    }

    private void SendToolResultApiResponse(int msgId, int userId, int roomId, string toolCallId, string toolCallResult, List<int>? historyMessagesIdList, DateTime time)
    {
        if (userId == -1 || roomId == -1)
        {
            Debug.LogError("Send Tool message failed");
            return;
        }

        eventBus.Publish(new SendToolResultsResponseCommand(msgId, userId, roomId, toolCallId, toolCallResult, historyMessagesIdList, time));
    }

    private void SendUserMsgApiResponse(int roomId, string messageJson, string? mentionedAgent)
    {
        ChatMessageData chatMessageData = SerializableObjectBase.FromJson<ChatMessageData>(messageJson);
        if (roomId == -1 || chatMessageData.Id == -1)
        {
            Debug.LogError("SendUser message failed");
            return;
        }

        eventBus.Publish(new SendUserMsgResponseCommand(roomId, chatMessageData, mentionedAgent));
    }

    private void OverrideMessageApiResponse(int messageId, string content)
    {
        if (messageId == -1 || string.IsNullOrEmpty(content))
        {
            Debug.LogError("Save edit message failed");
            return;
        }

        eventBus.Publish(new OverrideMessageResponseCommand(messageId, content));
    }

    private void ReceiveStream(Dictionary<string, object?> responseParams)
    {
        var userId = responseParams.GetData<int>("userId");
        var roomId = responseParams.GetData<int>("roomId");
        var msgId = responseParams.GetData<int>("msgId");
        var sliceIndex = responseParams.GetData<int>("sliceIndex");
        var author = responseParams.GetData<string>("author");
        var historyMessagesIdList = responseParams.GetData<List<int>?>("historyMessagesIdList");
        var msgSlice = responseParams.GetData<string?>("msgSlice");
        var toolCallsJson = responseParams.GetData<string?>("toolCallsJson");
        var time = responseParams.GetData<DateTime>("time");

        List<ToolCall>? toolCalls = null;
        if (toolCallsJson != null)
        {
            toolCalls = SerializableObjectBase.FromJson<List<ToolCall>>(toolCallsJson);
        }

        eventBus.Publish(new StreamSliceResponseCommand(userId, roomId, msgId, sliceIndex, author, historyMessagesIdList, msgSlice, time, toolCalls));
    }

    private void ReplyAssistantOptionsResponse(int roomId, List<string> options)
    {
        eventBus.Publish(new ReplyAssistantOptionsResponseCommand(roomId, options));
    }


    private void CreateProjectApiResponse(int projectId, string projectName, string projectSettings)
    {
        if (projectId == -1)
        {
            Debug.LogError("Create project failed");
            return;
        }

        eventBus.Publish(new CreateProjectResponseCommand(projectId, projectName, projectSettings));
    }
    
    private void DeleteProjectApiResponse(int projectId)
    {
        if (projectId == -1)
        {
            Debug.LogError("Delete project failed");
            return;
        }

        eventBus.Publish(new DeleteProjectResponseCommand(projectId));
    }
    
    private void CreateChatRoomApiResponse(int chatRoomId, int projectId, string chatRoomName)
    {
        if (chatRoomId == -1 || projectId == -1)
        {
            Debug.LogError("Create chat room failed");
            return;
        }

        eventBus.Publish(new CreateChatRoomResponseCommand(chatRoomId, projectId, chatRoomName));
    }

    private void SwitchChatRoomApiResponse(int chatRoomId, int projectId, List<string> messagesJson, int lastMessageId)
    {
        if (chatRoomId == -1 || projectId == -1)
        {
            Debug.LogError("Switch chat room failed");
            return;
        }

        List<ChatMessageData> messages = messagesJson.Select(messagejson => SerializableObjectBase.FromJson<ChatMessageData>(messagejson)).ToList();

        eventBus.Publish(new SwitchChatRoomResponseCommand(chatRoomId, projectId, messages, lastMessageId));
    }

    private void SwitchChatRoomBranchApiResponse(int chatRoomId, int messageId)
    {
        if (chatRoomId == -1 || messageId == -1)
        {
            Debug.LogError("Switch message branch failed");
            return;
        }

        eventBus.Publish(new SwitchChatRoomBranchResponseCommand(chatRoomId, messageId));
    }

    private void GetFileContentApiResponse(int fileId, string fileType, string fileContent)
    {
        eventBus.Publish(new GetFileContentResponseCommand(fileId, fileType, fileContent));
    }
}
